using B.S.Medical.Api.Read.Application.Command.Department;
using B.S.Medical.Api.Read.DTOS;
using B.S.Medical.Domain.Department;
using B.S.Medical.ErrorCode;
using B.S.Medical.Infrastructure.Interface;
using MediatR;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace B.S.Medical.Api.Read.Application.Handler.Department
{
    /// <summary>
    /// 根据院区ID查询科室级联结构的处理器
    /// </summary>
    public class GetDepartmentCascadeByCampusHandler : IRequestHandler<GetDepartmentCascadeByCampusCommand, ApiResult<List<DepartmentCascadeDTO>>>
    {
        private readonly IBaseRepository<ManageModel> _departmentRepository;
        private readonly ILogger<GetDepartmentCascadeByCampusHandler> _logger;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="departmentRepository">科室仓储</param>
        /// <param name="logger">日志</param>
        public GetDepartmentCascadeByCampusHandler(
            IBaseRepository<ManageModel> departmentRepository,
            ILogger<GetDepartmentCascadeByCampusHandler> logger)
        {
            _departmentRepository = departmentRepository;
            _logger = logger;
        }

        /// <summary>
        /// 处理根据院区ID查询科室级联结构的请求
        /// </summary>
        /// <param name="request">请求参数</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>科室级联结构结果</returns>
        public Task<ApiResult<List<DepartmentCascadeDTO>>> Handle(GetDepartmentCascadeByCampusCommand request, CancellationToken cancellationToken)
        {
            ApiResult<List<DepartmentCascadeDTO>> result = new ApiResult<List<DepartmentCascadeDTO>>();
            
            try
            {
                // 获取指定院区的所有未删除的科室
                var allDepartments = _departmentRepository.GetAll()
                    .Where(x => !x.IsDeleted && x.CampusId == request.CampusId)
                    .ToList();

                // 构建级联结构
                var rootDepartments = BuildDepartmentCascade(allDepartments);

                result.Data = rootDepartments;
                result.Code = ApiEnum.Success;
                result.Msg = "查询成功";
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "根据院区ID查询科室级联结构时发生错误");
                result.Code = ApiEnum.Error;
                result.Msg = "查询失败：" + ex.Message;
            }

            return Task.FromResult(result);
        }

        /// <summary>
        /// 构建科室级联结构
        /// </summary>
        /// <param name="departments">所有科室列表</param>
        /// <returns>顶级科室列表（包含子科室）</returns>
        private List<DepartmentCascadeDTO> BuildDepartmentCascade(List<ManageModel> departments)
        {
            // 获取所有顶级科室（ParetId为0的科室）
            var rootDepartments = departments
                .Where(d => d.ParetId == 0)
                .Select(d => new DepartmentCascadeDTO
                {
                    Id = d.Id,
                    DepartmentName = d.DepartmentName,
                    Children = new List<DepartmentCascadeDTO>()
                })
                .ToList();

            // 为每个顶级科室递归添加子科室
            foreach (var rootDept in rootDepartments)
            {
                AddChildDepartments(rootDept, departments);
            }

            return rootDepartments;
        }

        /// <summary>
        /// 递归添加子科室
        /// </summary>
        /// <param name="parent">父科室</param>
        /// <param name="allDepartments">所有科室列表</param>
        private void AddChildDepartments(DepartmentCascadeDTO parent, List<ManageModel> allDepartments)
        {
            // 查找当前科室的所有直接子科室
            var children = allDepartments
                .Where(d => d.ParetId == parent.Id)
                .Select(d => new DepartmentCascadeDTO
                {
                    Id = d.Id,
                    DepartmentName = d.DepartmentName,
                    Children = new List<DepartmentCascadeDTO>()
                })
                .ToList();

            // 设置子科室列表
            parent.Children = children;

            // 递归处理每个子科室
            foreach (var child in children)
            {
                AddChildDepartments(child, allDepartments);
            }
        }
    }
} 